﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using Blackworks.Logger;
using Monocle.DataModel;
using Monocle.DataModel.CustomDTO;

namespace Monocle.DataProvider
{
    public partial class SqlClient
    {
        /// <summary>
        /// Gets a pageitem by ID. 
        /// </summary>
        /// <param name="pageID">The primary key of the pageitem</param>
        /// <returns>The pageItem corresponding to the id</returns>
        public tPageItem GetPageItem(Guid pageID)
        {
            var sw = new System.Diagnostics.Stopwatch();
            sw.Start();

            tPageItem queryResult = null;
            try
            {
                using (var context = new MonocleEntities(_connectionString))
                {
                    // Disable proxies for serialization purposes
                    context.ContextOptions.ProxyCreationEnabled = false;

                    queryResult = (from b in context.tPageItems
                                   where b.PK_tPageItem == pageID
                                   select b).SingleOrDefault();
                }
            }
            catch (Exception e)
            {
                Log.WriteExceptionLogEntry(String.Format("The webmethod {0} failed with Exception: " + Environment.NewLine + "{1}" + Environment.NewLine + "Stacktrace:" + Environment.NewLine + "{2}" + Environment.NewLine + "InnerException: {3}", MethodBase.GetCurrentMethod().Name, e.Message, e.StackTrace, e.InnerException == null ? String.Empty : e.InnerException.Message), LogEntryPriority.Critical);
            }
            finally
            {
                sw.Stop();
                Log.WritePerformanceLogEntry(String.Format("Web method {0} runtime in milliseconds: {1}", MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds), LogEntryPriority.Low);
            }

            if (queryResult == null)
                throw new ArgumentException("No match was found for the supplied primary key", "pageID");

            return queryResult;
        }

        /// <summary>
        /// Get all items associated with a page
        /// </summary>
        /// <param name="pageID">ID of the page</param>
        /// <returns>List of DTOes</returns>
        public List<tPageItem> GetPageItemsByPage(Guid pageID)
        {
            var sw = new System.Diagnostics.Stopwatch();
            sw.Start();

            List<tPageItem> queryResult = null;
            try
            {
                using (var context = new MonocleEntities(_connectionString))
                {
                    // Disable proxies for serialization purposes
                    context.ContextOptions.ProxyCreationEnabled = false;

                    queryResult = (from b in context.tPageItems
                                   where b.FK_tPage == pageID
                                   select b).ToList();
                }
            }
            catch (Exception e)
            {
                Log.WriteExceptionLogEntry(String.Format("The webmethod {0} failed with Exception: " + Environment.NewLine + "{1}" + Environment.NewLine + "Stacktrace:" + Environment.NewLine + "{2}" + Environment.NewLine + "InnerException: {3}", MethodBase.GetCurrentMethod().Name, e.Message, e.StackTrace, e.InnerException == null ? String.Empty : e.InnerException.Message), LogEntryPriority.Critical);
            }
            finally
            {
                sw.Stop();
                Log.WritePerformanceLogEntry(String.Format("Web method {0} runtime in milliseconds: {1}", MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds), LogEntryPriority.Low);
            }

            if (queryResult == null)
                throw new ArgumentException("No match was found for the supplied primary key", "pageID");

            return queryResult;
        }

        /// <summary>
        /// Save a page to the database. Used for both updating and creating new entities
        /// </summary>
        /// <param name="dto">DTO to save</param>
        /// <returns>Saved DTO</returns>
        public tPageItem SavePageItem(tPageItem dto)
        {
            var sw = new System.Diagnostics.Stopwatch();
            sw.Start();

            tPageItem returnValue = dto;
            if (dto == null)
                throw new ArgumentNullException("dto", "argument is not allowed to be null");

            try
            {
                using (var context = new MonocleEntities(_connectionString))
                {
                    if (dto.Version == null)
                    {
                        context.tPageItems.AddObject(dto);
                    }
                    else
                    {
                        context.tPageItems.Attach(dto);
                        context.ObjectStateManager.ChangeObjectState(dto, EntityState.Modified);
                    }

                    context.SaveChanges();
                    returnValue = dto;
                }
            }
            catch (Exception e)
            {
                Log.WriteExceptionLogEntry(String.Format("The webmethod {0} failed with Exception: " + Environment.NewLine + "{1}" + Environment.NewLine + "Stacktrace:" + Environment.NewLine + "{2}" + Environment.NewLine + "InnerException: {3}", MethodBase.GetCurrentMethod().Name, e.Message, e.StackTrace, e.InnerException == null ? String.Empty : e.InnerException.Message), LogEntryPriority.Critical);
            }
            finally
            {
                sw.Stop();
                Log.WritePerformanceLogEntry(String.Format("Web method {0} runtime in milliseconds: {1}", MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds), LogEntryPriority.Low);
            }
            return returnValue;
        }

        /// <summary>
        /// Deletes a pageitem from the database
        /// </summary>
        /// <param name="dto">DTO to delete</param>
        public void DeletePageItem(tPageItem dto)
        {
            var sw = new System.Diagnostics.Stopwatch();
            sw.Start();

            if (dto == null)
                throw new ArgumentNullException("dto", "argument is not allowed to be null");

            try
            {
                using (var context = new MonocleEntities(_connectionString))
                {

                    context.tPageItems.Attach(dto);
                    context.tPageItems.DeleteObject(dto);
                    context.SaveChanges();
                }
            }
            catch (Exception e)
            {
                Log.WriteExceptionLogEntry(String.Format("The webmethod {0} failed with Exception: " + Environment.NewLine + "{1}" + Environment.NewLine + "Stacktrace:" + Environment.NewLine + "{2}" + Environment.NewLine + "InnerException: {3}", MethodBase.GetCurrentMethod().Name, e.Message, e.StackTrace, e.InnerException == null ? String.Empty : e.InnerException.Message), LogEntryPriority.Critical);
            }
            finally
            {
                sw.Stop();
                Log.WritePerformanceLogEntry(String.Format("Web method {0} runtime in milliseconds: {1}", MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds), LogEntryPriority.Low);
            }
        }

        /// <summary>
        /// Get a custom DTO containing the PageItem plus the module(s) attached to it
        /// </summary>
        /// <param name="pageItemID">Guid of the pageItem</param>
        /// <returns>PageItem DTO with Modules</returns>
        public PageItemWithModuleDTO GetPageItemWithModule(Guid pageItemID)
        {
            var sw = new System.Diagnostics.Stopwatch();
            sw.Start();

            PageItemWithModuleDTO queryResult = null;
            try
            {
                using (var context = new MonocleEntities(_connectionString))
                {
                    // Disable proxies for serialization purposes
                    context.ContextOptions.ProxyCreationEnabled = false;

                    var tPageItem = (from b in context.tPageItems
                                     where b.PK_tPageItem == pageItemID
                                     select b).SingleOrDefault();
                    var htmlModuleDTO = (from b in context.tHTMLs
                                         where b.FK_tPageItem == tPageItem.PK_tPageItem
                                         select b).SingleOrDefault();
                    var facebookModuleDTO = (from b in context.tFacebooks
                                             where b.FK_tPageItem == tPageItem.PK_tPageItem
                                             select b).SingleOrDefault();
                    queryResult = new PageItemWithModuleDTO()
                    {
                        tFacebook = facebookModuleDTO,
                        tHTML = htmlModuleDTO,
                        tPageItem = tPageItem
                    };
                }
            }
            catch (Exception e)
            {
                Log.WriteExceptionLogEntry(String.Format("The webmethod {0} failed with Exception: " + Environment.NewLine + "{1}" + Environment.NewLine + "Stacktrace:" + Environment.NewLine + "{2}" + Environment.NewLine + "InnerException: {3}", MethodBase.GetCurrentMethod().Name, e.Message, e.StackTrace, e.InnerException == null ? String.Empty : e.InnerException.Message), LogEntryPriority.Critical);
            }
            finally
            {
                sw.Stop();
                Log.WritePerformanceLogEntry(String.Format("Web method {0} runtime in milliseconds: {1}", MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds), LogEntryPriority.Low);
            }

            if (queryResult == null)
                throw new ArgumentException("No match was found for the supplied primary key", "pageID");

            return queryResult;
        }

        /// <summary>
        /// Get a list of custom DTO containing the PageItem plus the module(s) attached to it
        /// </summary>
        /// <param name="pageID">Guid of the page</param>
        /// <returns>PageItem DTO with Modules</returns>
        public List<PageItemWithModuleDTO> GetPageItemsWithModule(Guid pageID)
        {
            var sw = new System.Diagnostics.Stopwatch();
            sw.Start();

            var queryResult = new List<PageItemWithModuleDTO>();
            try
            {
                using (var context = new MonocleEntities(_connectionString))
                {
                    // Disable proxies for serialization purposes
                    context.ContextOptions.ProxyCreationEnabled = false;

                    var pageItemList = (from b in context.tPageItems
                                        where b.FK_tPage == pageID
                                        select b).ToList();
                    foreach (var item in pageItemList)
                    {
                        var htmlModuleDTO = (from b in context.tHTMLs
                                             where b.FK_tPageItem == item.PK_tPageItem
                                             select b).SingleOrDefault();
                        var facebookModuleDTO = (from b in context.tFacebooks
                                                 where b.FK_tPageItem == item.PK_tPageItem
                                                 select b).SingleOrDefault();

                        var dto = new PageItemWithModuleDTO()
                        {
                            tFacebook = facebookModuleDTO,
                            tHTML = htmlModuleDTO,
                            tPageItem = item
                        };
                        queryResult.Add(dto);
                    }
                }
            }
            catch (Exception e)
            {
                Log.WriteExceptionLogEntry(String.Format("The webmethod {0} failed with Exception: " + Environment.NewLine + "{1}" + Environment.NewLine + "Stacktrace:" + Environment.NewLine + "{2}" + Environment.NewLine + "InnerException: {3}", MethodBase.GetCurrentMethod().Name, e.Message, e.StackTrace, e.InnerException == null ? String.Empty : e.InnerException.Message), LogEntryPriority.Critical);
            }
            finally
            {
                sw.Stop();
                Log.WritePerformanceLogEntry(String.Format("Web method {0} runtime in milliseconds: {1}", MethodBase.GetCurrentMethod().Name, sw.ElapsedMilliseconds), LogEntryPriority.Low);
            }

            if (queryResult == null)
                throw new ArgumentException("No match was found for the supplied primary key", "pageID");

            return queryResult;
        }
    }
}
